package com.nervenets.template.controller.wx;

import com.alibaba.dubbo.config.annotation.Reference;
import com.nervenets.general.config.ApplicationProperties;
import com.nervenets.general.entity.WsMessage;
import com.nervenets.general.service.WebSocketService;
import com.nervenets.general.utils.StringUtils;
import com.nervenets.general.web.BaseController;
import com.nervenets.template.enumeration.Gender;
import com.nervenets.template.hibernate.domain.user.User;
import com.nervenets.template.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;

@Slf4j
@Api(value = "微信接口v1", tags = "微信相关接口")
@Controller
@RequestMapping("/api/wx")
public class WxController extends BaseController {
    @Resource
    private WxMpService wxMpService;
    @Reference(version = "1.0.0", check = false)
    private WebSocketService webSocketService;
    @Resource
    private UserService userService;
    @Resource
    private ApplicationProperties applicationProperties;

    @ApiOperation("微信跳转")
    @RequestMapping(method = RequestMethod.GET, value = "/auth")
    public ResponseEntity auth(@RequestParam(name = "code", defaultValue = "") String code,
                               @RequestParam(name = "state", defaultValue = "") String state,
                               @RequestParam(name = "toUrl", required = false) String toUrl
    ) {
        log.info(" ====>>code:{} ,state:{} ,toUrl:{}", code, state, toUrl);
        try {
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            if (org.apache.commons.lang3.StringUtils.isBlank(code)) {
                String url = String.format("http://%s/api/wx/auth?toUrl=%s", applicationProperties.getBaseDomain(), toUrl);
                log.info("openid url no code:{}", url);
                url = wxMpService.getOAuth2Service().buildAuthorizationUrl(url, "snsapi_userinfo", state);
                log.info("openid url no code:{}", url);
                map.add("Location", url);
                return new ResponseEntity(map, HttpStatus.MOVED_PERMANENTLY);
            } else {
                WxOAuth2AccessToken oAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
                log.info(" oAuth2AccessToken info :{}", oAuth2AccessToken);

                WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(oAuth2AccessToken, null);
                log.info(" oAuth2AccessToken userInfo :{}", wxMpUser);
                final String openId = wxMpUser.getOpenid();
                final String unionId = wxMpUser.getUnionId();

                User user = userService.findByOpenId(openId);
                if (null == user) user = new User();
                if (!StringUtils.isBlank(unionId)) {
                    user.setUnionId(unionId);
                }
                user.setName(wxMpUser.getNickname());
                user.setAvatar(wxMpUser.getHeadImgUrl());
                user.setGender(1 == wxMpUser.getSex() ? Gender.male : Gender.female);
                WxMpUser subscribe = wxMpService.getUserService().userInfo(openId);
                log.info(" UserService userInfo :{}", subscribe);
                user.setSubscribe(subscribe.getSubscribe());
                userService.save(user);

                userService.saveUserWxId(user, wxMpUser, wxMpService.getWxMpConfigStorage().getAppId());

                webSocketService.convertAndSend("wx_bind_" + user.getId(), new WsMessage("OK"));

                String url = String.format("http://%s/?v=%s", applicationProperties.getBaseDomain(), StringUtils.randomString(32));
                log.info("openid url with code :{}", url);
                map.add("Location", url);
                return new ResponseEntity(map, HttpStatus.MOVED_PERMANENTLY);
            }
        } catch (Exception ex) {
            log.error("openId is error=>code:{}", code, ex);
            return new ResponseEntity(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}
